Skip to content

Replace iterators with callbacks for progress reporting.#340

Open
cmaglie wants to merge 6 commits intomainfrom
remove-iter-2
Open

Replace iterators with callbacks for progress reporting.#340
cmaglie wants to merge 6 commits intomainfrom
remove-iter-2

Conversation

@cmaglie
Copy link
Copy Markdown
Member

@cmaglie cmaglie commented Apr 8, 2026

Motivation

This pull request refactors the way streaming and event-based APIs are handled throughout the codebase, moving from iterator-based interfaces to callback-based ones. This change simplifies the control flow, improves error handling, and removes the dependency on the iter package. Additionally, related test helpers and internal utilities were updated to match the new approach.

Change description

Test and helper code updates:

  • The SSE client helper for tests was refactored from an iterator-based API to a callback-based one, aligning with the new orchestrator API style and simplifying test logic.

Dependency and code cleanup:

  • Removed the internal iter.go helper and all uses of the iter package, since the new callback-based approach makes these utilities unnecessary.

Additional Notes

Reviewer checklist

  • PR addresses a single concern.
  • PR title and description are properly filled.
  • Changes will be merged in main.
  • Changes are covered by tests.
  • Logging is meaningful in case of troubleshooting.

Comment on lines -57 to +60
for appStatus, err := range orchestrator.AppStatusEvents(r.Context(), cfg, dockerCli, idProvider) {
if err != nil {
sseStream.SendError(render.SSEErrorData{Code: render.InternalServiceErr, Message: err.Error()})
continue
}
if err := orchestrator.AppStatusEvents(r.Context(), cfg, dockerCli, idProvider, func(appStatus orchestrator.AppInfo) {
sseStream.Send(render.SSEEvent{Type: "app", Data: appStatus})
}); err != nil {
sseStream.SendError(render.SSEErrorData{Code: render.InternalServiceErr, Message: err.Error()})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happen now if appstatusEvents returns an error? With iterators, there was a continue, and the SSE streaming stayed alive. Now any error terminate the session?

cmaglie added 6 commits April 8, 2026 18:53
* internal/orchestrator/orchestrator.go:

   - Removed "iter" import
   - StartApp, stopAppWithCmd, StopApp, StopAndDestroyApp, cleanAppCacheFiles, RestartApp: changed from returning iter.Seq[StreamMessage] to accepting a cb func(StreamMessage)
  parameter
   - All yield(msg) calls replaced with cb(msg), and if !yield(msg) { return } patterns simplified to just cb(msg) (early cancellation now relies purely on context)
   - StartDefaultApp and DeleteApp: updated internal calls to pass a callback
   - RestartApp: uses a stopHadError flag to avoid starting if stop failed

* Callers updated to pass a callback instead of ranging over the iterator:

   - internal/api/handlers/app_start.go and app_stop.go
   - cmd/arduino-app-cli/app/start.go, stop.go, restart.go, destroy.go
   - internal/orchestrator/system.go, cache.go, models.go
- AppStatusEvents now has the signature `func(..., cb func(AppInfo)) error`
- The callback only receives the happy-path AppInfo, and any error
  is returned directly to the caller.
- Updated the caller in internal/api/handlers/app_status.go to pass
  a callback (the old continue becomes a return in the callback body)
  The old error handling in the streaming phase, is now handled at
  function exit.
- AppLogs now takes cb func(LogMessage) as last param and returns error
- DockerLogConsumer.cb changed from `func(LogMessage) bool` to `func(LogMessage)`
- Removed shuttingDown atomic.Bool (the double-check lock for
  early-stop signalling is no longer needed)
- Removed "iter", "sync/atomic", and helpers imports
- SystemResources now takes `cb func(SystemResource)` as last param and
  returns `error`.
- All `if !yield(msg) { return }` patterns simplified to `cb(msg)`.
- Removed "iter" and helpers imports.
- NewSSEClient now takes `cb func(Event)` and returns `error`
- Context cancellation errors treated as nil (normal termination)
- `waitForUpgrade` uses `context.WithCancel` + `cancel()` inside the callback
  to replace the old break
- Made NewSSEClient private
- runUpgradeCommand, runAptCleanCommand, pullDockerImages, cleanupDockerContainers
  all changed from returning `iter.Seq2[string, error]` to `func(..., cb func(string)) error`
- Process kill-on-stop logic removed (context cancellation handles it)
- UpgradePackages caller updated accordingly
@lucarin91
Copy link
Copy Markdown
Contributor

I did a quick RP one of the bug funded here #344, if this is too long, we can merge that in the meantime

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants